using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;

namespace GGameFramework.Core.FSM
{
    /// <summary>
    /// 状态机调试器。
    /// </summary>
    /// <typeparam name="T">状态机持有者类型。</typeparam>
    public class FsmDebugger<T> where T : class
    {
        private readonly IFsm<T> m_Fsm;
        private readonly List<FsmDebugInfo> m_StateHistory;
        private readonly int m_MaxHistoryCount;

        /// <summary>
        /// 状态机调试信息。
        /// </summary>
        public struct FsmDebugInfo
        {
            public string StateName;
            public float Timestamp;
            public float StateTime;
            public string TransitionReason;

            public FsmDebugInfo(string stateName, float timestamp, float stateTime, string transitionReason = "")
            {
                StateName = stateName;
                Timestamp = timestamp;
                StateTime = stateTime;
                TransitionReason = transitionReason;
            }
        }

        /// <summary>
        /// 初始化状态机调试器的新实例。
        /// </summary>
        /// <param name="fsm">要调试的状态机。</param>
        /// <param name="maxHistoryCount">最大历史记录数量。</param>
        public FsmDebugger(IFsm<T> fsm, int maxHistoryCount = 100)
        {
            m_Fsm = fsm ?? throw new ArgumentNullException(nameof(fsm));
            m_MaxHistoryCount = maxHistoryCount;
            m_StateHistory = new List<FsmDebugInfo>();

            // 订阅状态转换事件
            if (fsm is Fsm<T> fsmImpl)
            {
                fsmImpl.OnStateChanged += OnStateChanged;
            }
        }

        /// <summary>
        /// 状态转换事件处理。
        /// </summary>
        /// <param name="fsm">状态机引用。</param>
        /// <param name="previousState">前一个状态。</param>
        /// <param name="currentState">当前状态。</param>
        private void OnStateChanged(IFsm<T> fsm, FsmState<T> previousState, FsmState<T> currentState)
        {
            string transitionReason = $"From {previousState?.GetStateName() ?? "None"} to {currentState?.GetStateName() ?? "None"}";
            
            AddStateHistory(currentState?.GetStateName() ?? "None", 
                          UnityEngine.Time.time, 
                          fsm.CurrentStateTime, 
                          transitionReason);
        }

        /// <summary>
        /// 添加状态历史记录。
        /// </summary>
        /// <param name="stateName">状态名称。</param>
        /// <param name="timestamp">时间戳。</param>
        /// <param name="stateTime">状态持续时间。</param>
        /// <param name="transitionReason">转换原因。</param>
        public void AddStateHistory(string stateName, float timestamp, float stateTime, string transitionReason = "")
        {
            FsmDebugInfo debugInfo = new FsmDebugInfo(stateName, timestamp, stateTime, transitionReason);
            m_StateHistory.Add(debugInfo);

            // 限制历史记录数量
            if (m_StateHistory.Count > m_MaxHistoryCount)
            {
                m_StateHistory.RemoveAt(0);
            }
        }

        /// <summary>
        /// 获取状态历史记录。
        /// </summary>
        /// <returns>状态历史记录。</returns>
        public List<FsmDebugInfo> GetStateHistory()
        {
            return new List<FsmDebugInfo>(m_StateHistory);
        }

        /// <summary>
        /// 获取状态机当前状态信息。
        /// </summary>
        /// <returns>当前状态信息字符串。</returns>
        public string GetCurrentStateInfo()
        {
            if (m_Fsm == null)
            {
                return "FSM is null";
            }

            StringBuilder sb = new StringBuilder();
            sb.AppendLine($"FSM: {m_Fsm.Name}");
            sb.AppendLine($"Owner: {m_Fsm.Owner?.GetType().Name ?? "None"}");
            //sb.AppendLine($"Current State: {m_Fsm.CurrentStateName}");
            sb.AppendLine($"State Time: {m_Fsm.CurrentStateTime:F2}s");
            sb.AppendLine($"Is Running: {m_Fsm.IsRunning}");
            sb.AppendLine($"Total States: {m_Fsm.StateCount}");

            return sb.ToString();
        }

        /// <summary>
        /// 获取状态机统计信息。
        /// </summary>
        /// <returns>统计信息字符串。</returns>
        public string GetStatistics()
        {
            if (m_StateHistory.Count == 0)
            {
                return "No state history available.";
            }

            StringBuilder sb = new StringBuilder();
            sb.AppendLine("=== FSM Statistics ===");
            
            // 状态访问频率统计
            Dictionary<string, int> stateFrequency = new Dictionary<string, int>();
            Dictionary<string, float> stateTotalTime = new Dictionary<string, float>();

            foreach (var info in m_StateHistory)
            {
                if (!stateFrequency.ContainsKey(info.StateName))
                {
                    stateFrequency[info.StateName] = 0;
                    stateTotalTime[info.StateName] = 0f;
                }
                stateFrequency[info.StateName]++;
                stateTotalTime[info.StateName] += info.StateTime;
            }

            sb.AppendLine("State Access Frequency:");
            foreach (var kvp in stateFrequency)
            {
                string stateName = kvp.Key;
                int frequency = kvp.Value;
                float totalTime = stateTotalTime[stateName];
                sb.AppendLine($"  {stateName}: {frequency} times, Total Time: {totalTime:F2}s");
            }

            // 最近的状态转换
            sb.AppendLine("\nRecent State Transitions:");
            int startIndex = Math.Max(0, m_StateHistory.Count - 10);
            for (int i = startIndex; i < m_StateHistory.Count; i++)
            {
                var info = m_StateHistory[i];
                sb.AppendLine($"  [{info.Timestamp:F2}s] {info.StateName} - {info.TransitionReason}");
            }

            return sb.ToString();
        }

        /// <summary>
        /// 清除历史记录。
        /// </summary>
        public void ClearHistory()
        {
            m_StateHistory.Clear();
        }

        /// <summary>
        /// 获取调试器的完整信息。
        /// </summary>
        /// <returns>完整的调试信息。</returns>
        public string GetFullDebugInfo()
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("=== FSM Debugger Information ===");
            sb.AppendLine();
            sb.AppendLine(GetCurrentStateInfo());
            sb.AppendLine();
            sb.AppendLine(GetStatistics());
            
            return sb.ToString();
        }
    }
}
